//
// RS Game Framework
// Copyright © 2009 Jedd Haberstro
// jhaberstro@gmail.com
// 
// $Id:
//

#include <rs/unittest/UnitTest.hpp>
#include <rs/math/Mathf.hpp>
#include <rs/math/HalfFloat.hpp>

namespace
{
    using namespace rs;
    using namespace rs::math;
    using namespace rs::unittest;
    
    Float const kHalfFloatEpsilon = 0.05f;
    
    RS_TEST_CASE(rs::math::HalfFloat, Conversion)
    {
        HalfFloat half(123.456f);
        Float conversion(half);
        RS_ASSERTF(Mathf::ApproximatelyEqual(conversion, 123.456f, kHalfFloatEpsilon), "Conversion to float failed. Converted value: %f", conversion);
    }
    
    RS_TEST_CASE(rs::math::HalfFloat, Comparison)
    {
        HalfFloat half1(1.0f);
        HalfFloat half2(1.0f);
        RS_ASSERT(half1 == half2, "operator == failed");
        RS_ASSERT(half1 <= half2, "operator <= failed for equality condition");
        RS_ASSERT(half1 >= half2, "operator >= failed for equality condition");
        
        half2 = HalfFloat(-1.0f);
        RS_ASSERT(half1 != half2, "operator != failed");
        RS_ASSERT(half2 < half1, "operator < failed");
        RS_ASSERT(half2 <= half1, "operator <= failed for less-than condition");
        RS_ASSERT(half1 > half2, "operator > failed");
        RS_ASSERT(half1 >= half2, "operator >= failed for greater-than condition");
    }
    
    RS_TEST_CASE(rs::math::HalfFloat, Arithmetic)
    {
        HalfFloat a = 10.0f, fa = 10.0f;
        HalfFloat b = 5.0f, fb = 5.0f;
        HalfFloat c = 7.5f;
        HalfFloat d = 7.5f;
        RS_ASSERT(Mathf::ApproximatelyEqual(Float(a + b), fa + fb, kHalfFloatEpsilon), "operator + failed");
        RS_ASSERT(Mathf::ApproximatelyEqual(Float(a - b), fa - fb, kHalfFloatEpsilon), "operator - failed");
        RS_ASSERT(Mathf::ApproximatelyEqual(Float(a * b), fa * fb, kHalfFloatEpsilon), "operator * failed");
        RS_ASSERT(Mathf::ApproximatelyEqual(Float(a / b), fa / fb, kHalfFloatEpsilon), "operator / failed");
        
        a += b, fa += fb;
        RS_ASSERT(Mathf::ApproximatelyEqual(a, fa, kHalfFloatEpsilon), "operator += failed");
        
        b -= a, fb -= fa;
        RS_ASSERT(Mathf::ApproximatelyEqual(b, fb, kHalfFloatEpsilon), "operator -= failed");
        
        a *= b, fa *= fb;
        RS_ASSERT(Mathf::ApproximatelyEqual(a, fa, kHalfFloatEpsilon), "operator *= failed");
        
        b /= a, fb /= fa;
        RS_ASSERT(Mathf::ApproximatelyEqual(b, fb, kHalfFloatEpsilon), "operator /= failed");
        
        RS_ASSERT(Mathf::ApproximatelyEqual(++a, ++fa, kHalfFloatEpsilon), "pre-increment failed");        
        RS_ASSERT(Mathf::ApproximatelyEqual(--a, --fa, kHalfFloatEpsilon), "pre-decrement failed");
        RS_ASSERT(Mathf::ApproximatelyEqual(a++, fa++, kHalfFloatEpsilon), "post-incremet failed");
        RS_ASSERT(Mathf::ApproximatelyEqual(a--, fa--, kHalfFloatEpsilon), "post-decrement failed");        
    }
}